//
//  SEEventReceiver.cpp
//  Space Explorer
//
//  Created by Yann Blaudin de Thé on 13/04/13.
//  Copyright (c) 2013 TeaTime. All rights reserved.
//

#include "SEEventReceiver.h"
#define VIT_DEPL 60


SEEventReceiver::SEEventReceiver() : _shift(false), _wireframe(false) {
    for (irr::u32 i=0; i<irr::KEY_KEY_CODES_COUNT; ++i)
        KeyIsDown[i]= false;
    
}

// This is the one method that we have to implement
bool SEEventReceiver::OnEvent(const irr::SEvent& event)
{
    switch (event.EventType) {
    // Remember whether each key is down or up
        case irr::EET_KEY_INPUT_EVENT:
            KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
            _shift = event.KeyInput.Shift;
            break;
    
//        case irr::EET_MOUSE_INPUT_EVENT:
//            if (event.MouseInput.Event == irr::EMIE_MOUSE_MOVED)
//            {
//                _cursor_pos = irr::core::position2d<irr::f32>(event.MouseInput.X, event.MouseInput.Y);
//                return true;
//            }
//            break;
            
        default:
            break;
    }
    
    if (_world)
        this->traite_evenements();
    
    if (event.EventType == irr::EET_KEY_INPUT_EVENT && event.KeyInput.Key == irr::KEY_ESCAPE && event.KeyInput.PressedDown)
    {
        _device->closeDevice();
        return true;
    }
    
    return false;
}

void SEEventReceiver::traite_evenements() {
    irr::scene::ICameraSceneNode* cam = _world->getIrrCamera();
    SpiceDouble warp;
    
    if (this->IsKeyDown(irr::KEY_KEY_W)) {
        _wireframe = !_wireframe;
        
        std::vector<SEPlanet*>::iterator planet_iterator;
        
        for (planet_iterator = _world->getPlanets().begin();
             planet_iterator != _world->getPlanets().end();
             planet_iterator++) {
            (*planet_iterator)->getIrrNode()->setMaterialFlag(irr::video::EMF_WIREFRAME, _wireframe);
        }
        
        this->resetKey(irr::KEY_KEY_W);
    }

    if (this->IsKeyDown(irr::KEY_KEY_P)) {
        takeScreenshot(_device);
        this->resetKey(irr::KEY_KEY_P);
    }

    irr::u32 key = int(irr::KEY_KEY_1);
    std::vector<SEPlanet*>::iterator planet_iterator;
    
    for (planet_iterator = _world->getPlanets().begin();
         planet_iterator != _world->getPlanets().end();
         planet_iterator++) {
        if (this->IsKeyDown(irr::EKEY_CODE(key))) {
            std::cout << "Astre : " << (*planet_iterator)->getName() << std::endl;
            cam->setPosition(vec3f());
            cam->setTarget((*planet_iterator)->getIrrPosition());
            if (this->IsShifted())
                _world->setCameraPos((*planet_iterator)->getPosition());
            this->resetKey(irr::KEY_KEY_1);
        }
        key += 1;
    }

    if (this->IsKeyDown(irr::KEY_KEY_T)) {
        warp = _world->setWarpCoeff(10.0f);
        this->resetKey(irr::KEY_KEY_T);
    }

    if (this->IsKeyDown(irr::KEY_KEY_R)) {
        warp = _world->setWarpCoeff(1/10.0f);
        this->resetKey(irr::KEY_KEY_R);
    }

    if (this->IsKeyDown(irr::KEY_KEY_Z)) {
        irr::f32 fov = cam->getFOV();
        cam->setFOV(fov - M_PI/180.0f);
        _world->getCockpit()->setFOV(180.0f/M_PI*fov - 1.0f);
        this->resetKey(irr::KEY_KEY_Z);
    }

    if (this->IsKeyDown(irr::KEY_KEY_X)) {
        irr::f32 fov = cam->getFOV();
        cam->setFOV(fov + M_PI/180.0f);
        _world->getCockpit()->setFOV(180.0f/M_PI*fov + 1.0f);
        this->resetKey(irr::KEY_KEY_X);
    }
    
    if (this->IsKeyDown(irr::KEY_NUMPAD5))
        cam->setPosition(vec3f());
    
    if (this->IsKeyDown(irr::KEY_NUMPAD6)) {
        vec3d pos = _world->getCameraPos();
        vec3d ph_targ;
        ph_targ.X = cam->getTarget().X;
        ph_targ.Y = cam->getTarget().Y;
        ph_targ.Z = cam->getTarget().Z;
        
        ph_targ.normalize();
        pos = pos + ph_targ*VIT_DEPL;
        
        _world->setCameraPos(pos);
    }
    
    if (this->IsKeyDown(irr::KEY_NUMPAD9)) {
        vec3d pos = _world->getCameraPos();
        vec3d ph_targ;
        ph_targ.X = cam->getTarget().X;
        ph_targ.Y = cam->getTarget().Y;
        ph_targ.Z = cam->getTarget().Z;
        
        ph_targ.normalize();
        pos = pos - ph_targ*VIT_DEPL;
        
        _world->setCameraPos(pos);
    }
    
    if (this->IsKeyDown(irr::KEY_NUMPAD1)) {
        vec3d pos = _world->getCameraPos();
        vec3d ph_targ, ph_up, ph_right;
        ph_targ.X = cam->getTarget().X;
        ph_targ.Y = cam->getTarget().Y;
        ph_targ.Z = cam->getTarget().Z;
        
        ph_up.X = cam->getUpVector().X;
        ph_up.Y = cam->getUpVector().Y;
        ph_up.Z = cam->getUpVector().Z;
        
        ph_right = ph_up.crossProduct(ph_targ);
        
        ph_right.normalize();
        pos = pos + ph_right*VIT_DEPL;
        
        _world->setCameraPos(pos);
    }
    
    if (this->IsKeyDown(irr::KEY_NUMPAD3)) {
        vec3d pos = _world->getCameraPos();
        vec3d ph_targ, ph_up, ph_right;
        ph_targ.X = cam->getTarget().X;
        ph_targ.Y = cam->getTarget().Y;
        ph_targ.Z = cam->getTarget().Z;
        
        ph_up.X = cam->getUpVector().X;
        ph_up.Y = cam->getUpVector().Y;
        ph_up.Z = cam->getUpVector().Z;
        
        ph_right = ph_up.crossProduct(ph_targ);
        
        ph_right.normalize();
        pos = pos - ph_right*VIT_DEPL;
        
        _world->setCameraPos(pos);
    }
    
    if (this->IsKeyDown(irr::KEY_NUMPAD8)) {
        vec3d pos = _world->getCameraPos();
        vec3d ph_up;
        ph_up.X = cam->getUpVector().X;
        ph_up.Y = cam->getUpVector().Y;
        ph_up.Z = cam->getUpVector().Z;
        
        ph_up.normalize();
        pos = pos - ph_up*VIT_DEPL;
        
        _world->setCameraPos(pos);
    }
    
    if (this->IsKeyDown(irr::KEY_NUMPAD2)) {
        vec3d pos = _world->getCameraPos();
        vec3d ph_up;
        ph_up.X = cam->getUpVector().X;
        ph_up.Y = cam->getUpVector().Y;
        ph_up.Z = cam->getUpVector().Z;
        
        ph_up.normalize();
        pos = pos + ph_up*VIT_DEPL;
        
        _world->setCameraPos(pos);
    }
    
}

bool SEEventReceiver::IsKeyDown(irr::EKEY_CODE keyCode) const {
    return KeyIsDown[keyCode];
}

bool SEEventReceiver::IsShifted() const {
    return _shift;
}

void SEEventReceiver::resetKey(irr::EKEY_CODE keyCode) {
    KeyIsDown[keyCode] = false;
}

void SEEventReceiver::setWorld(SEWorld* world) {
    _world = world;
    _device = world->getIrrDevice();
}
